import java.awt.LayoutManager;
import javax.swing.JPanel;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.*;
import javax.swing.JOptionPane;


import java.util.Iterator;




public class DrawingPanel extends JPanel {

	
	protected Graphics2D drawingZone;
	protected Color nameColor=Color.RED;
	protected Color backgroundColor=Color.WHITE; 
	protected Color stateColor=Color.BLACK;
	protected Color transitionColor=Color.BLUE;
	protected int statesSize=60;
	protected int spaceBetweenStates = 200;
	protected int spaceBetweenStatesAndBorder = spaceBetweenStates/2;
	protected Automaton autom;
	
	public DrawingPanel() {
		autom = new Automaton();
	}

	public DrawingPanel(Color n, Color bg, Color st, Color tr, int stSize,int spbtsp, int spbtstab, Automaton a) 
	{
		nameColor = n;
		backgroundColor=bg;
		stateColor=st;
		transitionColor=tr;
		statesSize= stSize;
		spaceBetweenStates = spbtsp;
		spaceBetweenStatesAndBorder = spbtstab;
		autom = a;
	}


	

	public void paint(Graphics draw)
	{			
		System.out.println("Drawing.");
		drawingZone=(Graphics2D)draw;
		drawingZone.setColor(backgroundColor);
		drawingZone.fillRect(0,0,getWidth(),getHeight());
		DisplayableAutomaton da = new DisplayableAutomaton(autom, spaceBetweenStates, spaceBetweenStatesAndBorder);
		//System.out.println(da.getDisplayedStates());
		drawAutomaton(da);
	
	}
	
	public void  drawAutomaton(DisplayableAutomaton dispAuto)
	{
		
		drawTransitions(dispAuto);
		drawStates(dispAuto);
		
	}

	public void  drawTransitions(DisplayableAutomaton dispAuto)
	{
	
		Iterator<DisplayableState> stateI = dispAuto.getDisplayedStates().iterator();
		State sTemp;
		Transition transTemp;
		DisplayableState ds1, ds2;
		Integer x1, y1, x2,y2;
		float xx1, yy1, xx2, yy2, xxMidle, yyMidle, xxMidleOffset, yyMidleOffset;
		float offset =  spaceBetweenStates/4;
		String tLabel;
		boolean reflexive;
		
		drawingZone.setColor(transitionColor);
		drawingZone.setStroke(new BasicStroke(1));
		
		while(stateI.hasNext())
			{drawingZone.setColor(transitionColor);
				ds1 =stateI.next();
				x1 = new Integer(ds1.getX());
				y1 = new Integer(ds1.getY());
				
				Iterator<Transition> transI = ds1.getTransitions().iterator();
				while(transI.hasNext())
				{
					transTemp = transI.next();
					sTemp = transTemp.getTargetState();
					//System.out.println(transTemp);
					//System.out.println(sTemp);
					
					
					if(sTemp instanceof DisplayableState )
					{
						
						
						ds2 = (DisplayableState)sTemp;
						tLabel = ds1.getStateName()+"->"+ds2.getStateName()+" : "+transTemp.getLabel();
						x2 = new Integer(ds2.getX());
						y2 = new Integer(ds2.getY());
						
						xx1 = x1.floatValue()+statesSize/2;
						yy1 = y1.floatValue()+statesSize/2;
						xx2 = x2.floatValue()+statesSize/2;
						yy2 = y2.floatValue()+statesSize/2; 
						
							xxMidle = (xx1 + xx2) / 2;
							yyMidle = (yy1 + yy2) / 2;
							
							
							offset *= -1;
													
							xxMidleOffset = xxMidle + offset;
							yyMidleOffset = yyMidle + offset;
							
							reflexive = false;
						if(xx1 == xx2 && yy1 == yy2)
						{
							reflexive = true;
							xx1 = xx1+(statesSize/4);
							xx2 = xx2-(statesSize/4);
							xxMidle = (xx1 + xx2) / 2;
							yyMidle = (yy1 + yy2) / 2;
							xxMidleOffset = xxMidle;
							yyMidleOffset = yyMidle - 2*statesSize;
						
						}
						//System.out.println ("(("+x1+","+y1+"),("+x2+","+y2+"))");
						
						drawingZone.setColor(transitionColor);
						drawingZone.draw(new QuadCurve2D.Float(xx1, yy1, xxMidleOffset, yyMidleOffset, xx2, yy2));
						drawingZone.setColor(nameColor);
						if(reflexive)
						{
							drawingZone.drawString(tLabel, xxMidle-20, yyMidle-statesSize);
						}
						else
						{
							drawingZone.drawString(tLabel, xxMidle-20, yyMidle);
						}
					}
				}
			}
		
		
		
		drawingZone.setColor(backgroundColor);
		
	}

	public void  drawStates(DisplayableAutomaton dispAuto)
	{
				
		Iterator<DisplayableState> stateI = dispAuto.getDisplayedStates().iterator();
		Integer x,y;
		String stateName;
		DisplayableState ds;
		
		
		drawingZone.setColor(stateColor);
		drawingZone.setStroke(new BasicStroke(1));
		
		while(stateI.hasNext())
		{
			
			ds = stateI.next();
			x = new Integer(ds.getX());
			y = new Integer(ds.getY());
			stateName = ds.getStateName();
			Ellipse2D.Float drawedState = new Ellipse2D.Float(x.floatValue(),y.floatValue(),statesSize,statesSize);
			
			drawingZone.setColor(stateColor);
			drawingZone.fill( drawedState );
			if(ds.isInitial)
			{
				drawingZone.setColor(transitionColor);
				Ellipse2D.Float drawedIni = new Ellipse2D.Float(x.floatValue()+statesSize/8,y.floatValue()+statesSize/8,statesSize*3/4,statesSize*3/4);
				
				drawingZone.fill( drawedIni );
			}
			if(ds.isFinal)
			{
				drawingZone.setColor(backgroundColor);
				Ellipse2D.Float drawedFin = new Ellipse2D.Float(x.floatValue()+statesSize/8,y.floatValue()+statesSize/8,statesSize*3/4,statesSize*3/4);
				
				drawingZone.fill( drawedFin );
			}
			drawingZone.setColor(nameColor);
			drawingZone.drawString(stateName, x.floatValue()+2, y.floatValue()+5+statesSize/2);
		}
			
		drawingZone.setColor(backgroundColor);
		
		
	}

	
	
	
	
	
	
	
	
	
	
	
	
	public Automaton getAutom() {
		return autom;
	}

	public void setAutom(Automaton autom) {
		this.autom = autom;
	}

	public Color getBackgroundColor() {
		return backgroundColor;
	}

	public void setBackgroundColor(Color backgroundColor) {
		this.backgroundColor = backgroundColor;
	}

	public Graphics2D getDrawingZone() {
		return drawingZone;
	}

	public void setDrawingZone(Graphics2D drawingZone) {
		this.drawingZone = drawingZone;
	}

	public Color getStateColor() {
		return stateColor;
	}

	public void setStateColor(Color stateColor) {
		this.stateColor = stateColor;
	}

	public int getStatesSize() {
		return statesSize;
	}

	public void setStatesSize(int statesSize) {
		this.statesSize = statesSize;
	}

	public Color getTransitionColor() {
		return transitionColor;
	}

	public void setTransitionColor(Color transitionColor) {
		this.transitionColor = transitionColor;
	}
	
}
